using System;

namespace Tycho.Parser.Peg {
    public class BeginBlockProduction : Production {
        private readonly IProduction IndentationTerminal;

        public BeginBlockProduction () {
            IndentationTerminal = IndentationProduction.CreateTerminal ();
            ErrorInformation = new KeywordErrorInformation ("{");
        }

        public static Terminal CreateTerminal () {
            return new Terminal (new BeginBlockProduction ());
        }

        protected override ParseResult ReallyParse (char[] source, int startIndex, ParseContext context, string sourceString, ParseEnvironment parseEnvironment) {
            var indentResult = IndentationTerminal.Parse (source, startIndex, context, sourceString, parseEnvironment);

            int index;
            if (indentResult != null) {
                index = indentResult.Index;
            } else {
                index = startIndex;
            }

            if (index < source.Length && source[index] == '{') {
                startIndex = index;

                ParseContext newContext = context.Clone ();
                newContext.BracketDepth++;

                index++;

                var newLineResult = IndentationTerminal.Parse (source, index, newContext, sourceString, parseEnvironment);

                if (newLineResult != null) {
                    index = newLineResult.Index;
                    newContext = newLineResult.Context;
                }

                return new ParseResult (index, CreateTerm (parseEnvironment.SourceFileInformation.CreateSourceInformation (startIndex, 1)), newContext);
            } else if (indentResult != null && context.BracketDepth == 0) {
                var indentationTerm = (IndentationTerm) indentResult.Term;
                if (indentationTerm.GetIndentation (context.LastIndent) == Indentation.BeginBlock) {
                    return new ParseResult (index, CreateTerm (parseEnvironment.SourceFileInformation.CreateSourceInformation (startIndex, index - startIndex)), indentResult.Context);
                }
            }

            return null;
        }

        private static KeywordTerm CreateTerm (SourceInformation sinfo) {
            return new KeywordTerm ("{", sinfo);
        }
    }
}